<?php
// 应用公共文件

error_reporting(E_ERROR | E_PARSE );

//创建一个新名字
function get_newName()
{
    return md5(uniqid(md5(microtime(true)),true));
}

//获取随机数字
function get_randNum($len=6)
{
    $chars = '0123456789';
    $str = '';
    for ( $i = 0; $i < $len; $i++ )
    {
        $str .= $chars[mt_rand(0, strlen($chars) - 1) ];
    }
    return $str;
}

//获取字符串中英文混合长度
function get_strlen($str,$charset='utf-8'){
    if($charset=='utf-8') $str = iconv('utf-8','gb2312',$str);
    $num = strlen($str);
    $cnNum = 0;
    for($i=0;$i<$num;$i++){
        if(ord(substr($str,$i+1,1))>127){
            $cnNum++;
            $i++;
        }
    }
    $enNum = $num-($cnNum*2);
    return $cnNum*2+$enNum;
}

/**写日志*/
function logs($data='', $file='', $mode=FILE_APPEND)
{
    $logs_dir ='./logs/';
    if( !file_exists($logs_dir) )
    {
        @mdir($logs_dir);
    }
    $file= ($file=='' ? 'log-' : $file.'-').date('Ymd',time()).'.log';

    file_put_contents($logs_dir . $file, date('Y-m-d H:i:s',time()).' '.$data.PHP_EOL, $mode);
}

//获取一个字符串中的后缀
function get_extension($str)
{
    $str= explode('.', $str);
    return end($str);
}

//获取一个字符串中的文件名
function get_filename($str)
{
    if($str==''){return '';}
    if(stripos($str, '/') !==false)
    {
        $str = substr($str, strrpos($str, '/') + 1, strlen($str));
    }
    return substr($str, 0, strrpos($str, '.'));
}

//返回某目录下的所有文件(不包括子目录)
function getfiles($dir)
{
    if($dir !='' && substr($dir, strlen($dir)-1)!='')
    {
        $dir .='/';
    }
    $row=array();
    if (is_dir($dir)) {
        if ($di = opendir($dir)) {
            while (($file = readdir($di)) !== false) {
                if(is_file($dir.$file) && $file !='.' && $file !='..')
                {
                    $row[]=$file;
                }
            }
            closedir($di);
        }
    }
    return $row;
}

//删除文件
function del_file($file){
    $delete = @unlink($file);
    clearstatcache();
    if(@file_exists($file)){
        $filesys = eregi_replace("/","\\",$file);
        $delete = @system("del $filesys");
        clearstatcache();
        if(@file_exists($file)){
            $delete = @chmod ($file, 0777);
            $delete = @unlink($file);
            $delete = @system("del $filesys");
        }
    }
    clearstatcache();
    if(@file_exists($file)){
        return false;
    }else{
        return true;
    }
}

//创建目录
function mdir($directoryName) {
    $directoryName = str_replace("\\","/",$directoryName);
    $dirNames = explode('/', $directoryName);
    $total = count($dirNames) ;
    $temp = '';
    for($i=0; $i<$total; $i++) {
        $temp .= $dirNames[$i].'/';
        if (!is_dir($temp)) {
            $oldmask = umask(0);
            if (!mkdir($temp, 0777)) exit("can't md dir $temp");
            umask($oldmask);
        }
    }
    return true;
}

/**@name 获取随机字符串，大小写字母+数字，转变不区分大小写
 *@param $len 长度
 *@param $ignoreCase 忽略大小写
 * */
function get_salt($len=8, $ignoreCase=true)
{
    //return substr(uniqid(rand()), -$len);
    $discode="123546789wertyupkjhgfdaszxcvbnm".($ignoreCase?'': 'QABCDEFGHJKLMNPRSTUVWXYZ');
    $code_len = strlen($discode);
    $code = "";
    for($j=0; $j<$len; $j++){
        $code .= $discode[rand(0, $code_len-1)];
    }
    return $code;
}

//加密字符串
function encryptStr($val, $salt='')
{
    return md5(md5(trim($val)).$salt);
}

/**@name 是否只有数字和逗号
 *@param str 字符串
 * */
function isNumComma($str)
{
    return preg_match("/^[\d,]+$/", $str);
}

/**@name 是否只有数字
 *@param str 字符串
 * */
function is_num($str)
{
    return preg_match("/^[0-9]+$/", $str);
}

/**@name 字母和数字
 *@param str 字符串
 * */
function is_enAndnum($str, $start=1, $end=16)
{
    return preg_match("/^[A-Za-z0-9]{".$start.",".$end."}$/", $str);
}

/**是否只有字母*/
function isLetter($str)
{
    return preg_match("/^[a-zA-Z]+$/", $str);
}

/**@name 是否email
 * @param   string   $str
 */
function is_email($str)
{
    return preg_match("/^[a-zA-Z]+$/", $str);
}

/**@name 用户名：中文、字母、数字、“-”“_”的组合
 * @param   string   $str
 */
function is_username($str)
{
    return preg_match('/^[A-Za-z0-9_\-\x{4e00}-\x{9fa5}]+$/u', $str);
}

/**@name 收货人：中文、字母和空格的组合
 * @param   string   $str
 */
function is_consignee($str)
{
    return preg_match('/^(([\x{4e00}-\x{9fa5}])([\x{4e00}-\x{9fa5}·]){0,10}([\x{4e00}-\x{9fa5}]))|([a-zA-Z]([a-zA-Z]|\s){2,20})+$/u', $str);
}

/**是否手机号码
 * @param   string   $str
 */
function is_mobile($str)
{
    return preg_match("/^(13|14|15|18|17)[0-9]{9}$/", $str);
}

/**是否固定电话
 * @param   string   $str
 */
function is_tel($str)
{
    return preg_match("/^[0-9]{1,4}(-|[0-9])\d{5,15}$/", $str);
}

/**将字符串匿名化   比如 158***545
 * */
function format_anon($val, $start_len=1, $end_len=1, $cover_len=3, $cover='*')
{
    $cover_str="";
    for ($i=0; $i < $cover_len; $i++) {
        $cover_str .=$cover;
    }
    return mb_substr($val, 0,$start_len,'utf-8').$cover_str.mb_substr($val, mb_strlen($val,'utf-8')-$end_len,$end_len,'utf-8');
}

/**
 *将一个字串中含有全角的数字字符、字母、空格或'%+-()'字符转换为相应半角字符
 * @access    public
 * @param     string $str     待转换字串
 * @return    string  $str    处理后字串
 */
function make_semiangle($str) {
    $arr = array('０' => '0', '１' => '1', '２' => '2', '３' => '3', '４' => '4','５' => '5', '６' => '6', '７' => '7', '８' => '8', '９' => '9', 'Ａ' => 'A', 'Ｂ' => 'B', 'Ｃ' => 'C', 'Ｄ' => 'D', 'Ｅ' => 'E','Ｆ' => 'F', 'Ｇ' => 'G', 'Ｈ' => 'H', 'Ｉ' => 'I', 'Ｊ' => 'J', 'Ｋ' => 'K', 'Ｌ' => 'L', 'Ｍ' => 'M', 'Ｎ' => 'N', 'Ｏ' => 'O','Ｐ' => 'P', 'Ｑ' => 'Q', 'Ｒ' => 'R', 'Ｓ' => 'S', 'Ｔ' => 'T','Ｕ' => 'U', 'Ｖ' => 'V', 'Ｗ' => 'W', 'Ｘ' => 'X', 'Ｙ' => 'Y','Ｚ' => 'Z', 'ａ' => 'a', 'ｂ' => 'b', 'ｃ' => 'c', 'ｄ' => 'd','ｅ' => 'e', 'ｆ' => 'f', 'ｇ' => 'g', 'ｈ' => 'h', 'ｉ' => 'i','ｊ' => 'j', 'ｋ' => 'k', 'ｌ' => 'l', 'ｍ' => 'm', 'ｎ' => 'n','ｏ' => 'o', 'ｐ' => 'p', 'ｑ' => 'q', 'ｒ' => 'r', 'ｓ' => 's', 'ｔ' => 't', 'ｕ' => 'u', 'ｖ' => 'v', 'ｗ' => 'w', 'ｘ' => 'x', 'ｙ' => 'y', 'ｚ' => 'z','（' => '(', '）' => ')', '〔' => '[', '〕' => ']', '【' => '[','】' => ']', '〖' => '[', '〗' => ']', '“' => '[', '”' => ']','‘' => '[', '’' => ']', '｛' => '{', '｝' => '}', '《' => '<','》' => '>','％' => '%', '＋' => '+', '—' => '-', '－' => '-', '～' => '-','：' => ':', '。' => '.', '、' => ',', '，' => '.', '、' => '.',     '；' => ',', '？' => '?', '！' => '!', '…' => '-', '‖' => '|', '”' => '"', '’' => '`', '‘' => '`', '｜' => '|', '〃' => '"','　' => ' ');
    return strtr($str, $arr);
}

//检测审查的文字
function check_censor($field, $word='keepword')
{
    $words =get_cache('censor', $path = cache_data, $word);
    $exp = '/^('.str_replace(array('\\*', "\r\n", ' '), array('.*', '|', ''), preg_quote(($words = trim($words)), '/')).')$/i'; //print $words.' '.$exp;
    if($words && @preg_match($exp, $field)) {
        return false;
    }
    return true;
}

// $string： 明文 或 密文
// $operation：DECODE表示解密,其它表示加密
// $key： 密匙
// $expiry：密文有效期
function endecrypt($string, $operation = 'DECODE', $key = 'clxf.com', $expiry = 0)
{
    // 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
    $ckey_length = 4;

    // 密匙
    $key = md5($key ? $key : $ym_auth_key);

    // 密匙a会参与加解密
    $keya = md5(substr($key, 0, 16));
    // 密匙b会用来做数据完整性验证
    $keyb = md5(substr($key, 16, 16));
    // 密匙c用于变化生成的密文
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
    // 参与运算的密匙
    $cryptkey = $keya.md5($keya.$keyc);
    $key_length = strlen($cryptkey);
    // 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，解密时会通过这个密匙验证数据完整性
    // 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
    $string_length = strlen($string);
    $result = '';
    $box = range(0, 255);
    $rndkey = array();
    // 产生密匙簿
    for($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }
    // 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度
    for($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }
    // 核心加解密部分
    for($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        // 从密匙簿得出密匙进行异或，再转成字符
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }
    if($operation == 'DECODE') {
        // substr($result, 0, 10) == 0 验证数据有效性
        // substr($result, 0, 10) - time() > 0 验证数据有效性
        // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性
        // 验证数据有效性，请看未加密明文的格式
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
            return substr($result, 26);
        } else {
            return '';
        }
    } else {
        // 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
        // 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
        return $keyc.str_replace('=', '', base64_encode($result));
    }
}

/*时间函数*/
function time_diff($begin_time,$end_time)
{
    if($begin_time < $end_time){
        $starttime = $begin_time;
        $endtime = $end_time;
    }else{
        $starttime = $end_time;
        $endtime = $begin_time;
    }

    //计算天数
    $timediff = $endtime-$starttime;
    $days = intval($timediff/86400);
    //计算小时数
    $remain = $timediff%86400;
    $hours = intval($remain/3600);
    //计算分钟数
    $remain = $remain%3600;
    $mins = intval($remain/60);
    //计算秒数
    $secs = $remain%60;
    return array("day" => $days,"hour" => $hours,"min" => $mins,"sec" => $secs);
}

/** 以post方式提交data到对应的接口url
 * @param string $url  url
 * @param string $data  需要post的数据, 可以是数组、xml、json、字符串等
 * @param int $second  url执行超时时间，默认30s
 * @param string $sslcert_path 证书cert路径
 * @param string $sslcert_type 证书cert类型
 * @param string $sslkey_path  证书key路径
 * @param string $sslkey_type  证书key类型
 * @throws Exception
 */
function post_url($url, $data='', $timeout = 30, $sslcert_path='', $sslcert_type='PEM',$sslkey_path='', $sslkey_type='PEM',$verifypeer=FALSE,$verifyhost=0)
{
    $ch = curl_init();
    //设置超时
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);

    //如果有配置代理这里就设置代理
    if(CURL_PROXY_HOST != "0.0.0.0" && CURL_PROXY_PORT != 0){
        curl_setopt($ch,CURLOPT_PROXY, CURL_PROXY_HOST);
        curl_setopt($ch,CURLOPT_PROXYPORT, CURL_PROXY_PORT);
    }
    curl_setopt($ch,CURLOPT_URL, $url);
    curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, $verifypeer);
    curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, $verifyhost);//是否严格校验
    //设置header
    curl_setopt($ch, CURLOPT_HEADER, FALSE);
    //要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

    if($sslcert_path !== ''){//使用证书：cert
        curl_setopt($ch,CURLOPT_SSLCERTTYPE, $sslcert_type);
        curl_setopt($ch,CURLOPT_SSLCERT, $sslcert_path);
    }
    if($sslkey_path !== ''){
        curl_setopt($ch,CURLOPT_SSLKEYTYPE, $sslkey_type);
        curl_setopt($ch,CURLOPT_SSLKEY, $sslkey_path);
    }
    //post提交方式
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

    $data = curl_exec($ch); //var_dump($data);

    $res =array('err'=>'', 'res'=>'', 'data'=>array());

    if($data){
        curl_close($ch);
        $res['data'] =$data;
    } else {
        $error = curl_errno($ch);
        $info = curl_getinfo($ch);
        curl_close($ch);
        $res['err'] = "curl出错，错误码:$error http_code=".$info['http_code'];
    }
    return $res;
}

/**通过curl方式获取远程图片到本地
 *@param $url 完整的图片地址
 *@param $filename 文件名
 */
function get_curl_file($url = "", $filename = "" , $time=6)
{
    if(!is_dir($filename)) {
        mdir(str_replace(basename($filename), '', $filename));
    }
    //去除URL连接上面可能的引号
    $url = preg_replace( '/(?:^[\'"]+|[\'"\/]+$)/', '', $url );
    $ch = curl_init();
    $fp = fopen($filename,'wb');
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_FILE,$fp);
    curl_setopt($ch,CURLOPT_HEADER,0);
    curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
    curl_setopt($ch,CURLOPT_TIMEOUT, $time);
    curl_exec($ch);
    curl_close($ch);
    fclose($fp);
    return '';
}

//获取完整url
function get_fullurl()
{
    global $ym_is_https;
    $protocal = isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443' && $ym_is_https==1 ? 'https://' : 'http://';
    $php_self = $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
    $path_info = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
    $req_url = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $php_self.(isset($_SERVER['QUERY_STRING']) ? '?'.$_SERVER['QUERY_STRING'] : $path_info);
    return $protocal.(isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '').$req_url;
}

//获取用户设备类型
function get_client()
{
    global $ym_client;
    if(isset($_SESSION['client']))
    {
        return $_SESSION['client'];
    }
    session_start();
    if($ym_client && ($ym_client ==client_pc || $ym_client ==client_m || $ym_client ==client_app))
    {
        $_SESSION['client'] = $ym_client;
        return $ym_client;
    }
    include("./inc/lib/mobile_detect.php");
    $detect = new Mobile_Detect();
    if($detect->isMobile())
    {
        $_SESSION['client'] = client_m;
        return client_m;
    }else {
        $_SESSION['client'] = client_pc;
        return client_pc;
    }
}

/**是否微信浏览器*/
function is_weixin()
{
    if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'micromessenger') === false)
    {
        return false;
    }
    return true;
}

//裁剪图片
function resize_img($filename, $type='', $width=0, $height=0, $thumb_type=-1)
{
    $img = new image();
    if($type !='')
    {
        $tb_config = get_thumb_config(0, $type);
        $tb_type = $tb_config['thumb_type'];
    }
    else {
        $tb_type = isset($ym_thumb_type) ? intval($ym_thumb_type) :1;
    }
    $tb_type = $thumb_type ==-1 ? $tb_type :$thumb_type;
    $img->param($filename)->thumb($filename, ($width !=0 ? $width : $tb_config['width']) ,($height!=0 ? $height : $tb_config['height']), $tb_type);
}

//获取IP地址
function getIp($type=1)
{
    if(!empty($_SERVER["HTTP_CLIENT_IP"]))
    {
        $cip = $_SERVER["HTTP_CLIENT_IP"];
    }
    else if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))
    {
        $cip = $_SERVER["HTTP_X_FORWARDED_FOR"];
    }
    else if(!empty($_SERVER["REMOTE_ADDR"]))
    {
        $cip = $_SERVER["REMOTE_ADDR"];
    }
    else
    {
        $cip = '';
    }
    preg_match("/[\d\.]{7,15}/", $cip, $cips);
    $cip = isset($cips[0]) ? $cips[0] : '127.0.0.1';
    if($type===0){
        $cip = sprintf('%u',ip2long($cip));
    }
    unset($cips);
    return $cip;
}

//字符串过滤
function filter($str)
{
    $str=str_replace(".html","",$str);
    $str=str_replace(".htm","",$str);
    $str=str_replace(".asp","",$str);
    $str=str_replace(".php","",$str);
    $str=str_replace(".jsp","",$str);
    $str=str_replace(".","",$str);
    $str=str_replace("/","",$str);
    $str=str_replace("&","",$str);
    $str=str_replace("*","",$str);
    $str=str_replace("%","",$str);
    $str=str_replace("#","",$str);
    $str=str_replace("!","",$str);
    $str=str_replace("(","",$str);
    $str=str_replace(")","",$str);
    $str=str_replace("-","_",$str);
}

function filter_keyword( $string ) {
    $keyword = 'select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|and|union|order|or|into|load_file|outfile';
    $arr = explode( '|', $keyword );
    $result = str_ireplace( $arr, '', $string );
    return $result;
}

//jwt加密
function jwt_encode($userinfo, $secret){
    $header_arr = array(
        'typ' => 'JWT',		//token类型
        'alg' => 'HS256'	//加密方法
    );
    $payload_arr = array(
        'iss' => 'www.clxf.com',	//发行方
        'exp' => '2592000',		//有效期30天
        'userinfo' => $userinfo,		//用户信息
        'pubtime' => time()		//发布时间
    );
    $header = base64_encode(json_encode($header_arr));
    $payload = base64_encode(json_encode($payload_arr));
    $signature = base64_encode(hash_hmac('sha256', $header . "." . $payload, $secret, FALSE));
    $tokens = $header . "." . $payload . "." . $signature;
    return $tokens;
}

//jwt解密
function jwt_decode($tokens, $secret){
    if(empty($tokens)) return false;
    $arr = explode(".",$tokens);
    $header = $arr[0];
    $payload = $arr[1];
    $signature = base64_encode(hash_hmac('sha256', $header . "." . $payload, $secret, FALSE));
    if($signature==$arr[2]){
        $header_arr = json_decode(base64_decode($header));
        $payload_arr = json_decode(base64_decode($payload));
        $timediff = time() - $payload_arr->pubtime;
        if($timediff >= $payload_arr->exp){
            return false;
        }
        //$data['h'] = $header_arr;
        $data = $payload_arr;
        return $data;
    }
    else {
        return false;
    }
}

function return_size($bytes, $separator='')
{
    //utility functions
    $kb = 1024;          //Kilobyte
    $mb = 1024 * $kb;    //Megabyte
    $gb = 1024 * $mb;    //Gigabyte
    $tb = 1024 * $gb;    //Terabyte

    if($bytes < $kb)
        return $bytes."{$separator}B";
    else if($bytes < $mb)
        return round($bytes/$kb,2)."{$separator}KB";
    else if($bytes < $gb)
        return round($bytes/$mb,2)."{$separator}MB";
    else if($bytes < $tb)
        return round($bytes/$gb,2)."{$separator}GB";
    else
        return round($bytes/$tb,2)."{$separator}TB";
}

function getDirSize($dir)
{
    $sizeResult = 0;
    $handle = opendir($dir);
    while (false !== ($FolderOrFile = readdir($handle)))
    {
        if($FolderOrFile != "." && $FolderOrFile != "..") {
            if (is_dir("$dir/$FolderOrFile")) {
                $sizeResult += getDirSize("$dir/$FolderOrFile");
            } else {
                $sizeResult += filesize("$dir/$FolderOrFile");
            }
        }
    }
    closedir($handle);
    return $sizeResult;
}

